

<!DOCTYPE html>

<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>4. Building a JIT: Extreme Laziness - Using Compile Callbacks to JIT from ASTs &#8212; LLVM 9 documentation</title>
    <link rel="stylesheet" href="../_static/llvm-theme.css" type="text/css" />
    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
    <script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
    <script src="../_static/jquery.js"></script>
    <script src="../_static/underscore.js"></script>
    <script src="../_static/doctools.js"></script>
    <script src="../_static/language_data.js"></script>
    <link rel="index" title="Index" href="../genindex.html" />
    <link rel="search" title="Search" href="../search.html" />
    <link rel="next" title="5. Building a JIT: Remote-JITing – Process Isolation and Laziness at a Distance" href="BuildingAJIT5.html" />
    <link rel="prev" title="3. Building a JIT: Per-function Lazy Compilation" href="BuildingAJIT3.html" />
<style type="text/css">
  table.right { float: right; margin-left: 20px; }
  table.right td { border: 1px solid #ccc; }
</style>

  </head><body>
<div class="logo">
  <a href="../index.html">
    <img src="../_static/logo.png"
         alt="LLVM Logo" width="250" height="88"/></a>
</div>

    <div class="related" role="navigation" aria-label="related navigation">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="BuildingAJIT5.html" title="5. Building a JIT: Remote-JITing – Process Isolation and Laziness at a Distance"
             accesskey="N">next</a> |</li>
        <li class="right" >
          <a href="BuildingAJIT3.html" title="3. Building a JIT: Per-function Lazy Compilation"
             accesskey="P">previous</a> |</li>
  <li><a href="http://llvm.org/">LLVM Home</a>&nbsp;|&nbsp;</li>
  <li><a href="../index.html">Documentation</a>&raquo;</li>

          <li class="nav-item nav-item-1"><a href="index.html" accesskey="U">LLVM Tutorial: Table of Contents</a> &#187;</li>
        <li class="nav-item nav-item-this"><a href=""><span class="section-number">4. </span>Building a JIT: Extreme Laziness - Using Compile Callbacks to JIT from ASTs</a></li> 
      </ul>
    </div>


    <div class="document">
      <div class="documentwrapper">
          <div class="body" role="main">
            
  <div class="section" id="building-a-jit-extreme-laziness-using-compile-callbacks-to-jit-from-asts">
<h1><span class="section-number">4. </span>Building a JIT: Extreme Laziness - Using Compile Callbacks to JIT from ASTs<a class="headerlink" href="#building-a-jit-extreme-laziness-using-compile-callbacks-to-jit-from-asts" title="Permalink to this headline">¶</a></h1>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><p><a class="reference internal" href="#chapter-4-introduction" id="id1">Chapter 4 Introduction</a></p></li>
<li><p><a class="reference internal" href="#full-code-listing" id="id2">Full Code Listing</a></p></li>
</ul>
</div>
<p><strong>This tutorial is under active development. It is incomplete and details may
change frequently.</strong> Nonetheless we invite you to try it out as it stands, and
we welcome any feedback.</p>
<div class="section" id="chapter-4-introduction">
<h2><a class="toc-backref" href="#id1"><span class="section-number">4.1. </span>Chapter 4 Introduction</a><a class="headerlink" href="#chapter-4-introduction" title="Permalink to this headline">¶</a></h2>
<p>Welcome to Chapter 4 of the “Building an ORC-based JIT in LLVM” tutorial. This
chapter introduces the Compile Callbacks and Indirect Stubs APIs and shows how
they can be used to replace the CompileOnDemand layer from
<a class="reference external" href="BuildingAJIT3.html">Chapter 3</a> with a custom lazy-JITing scheme that JITs
directly from Kaleidoscope ASTs.</p>
<p><strong>To be done:</strong></p>
<p><strong>(1) Describe the drawbacks of JITing from IR (have to compile to IR first,
which reduces the benefits of laziness).</strong></p>
<p><strong>(2) Describe CompileCallbackManagers and IndirectStubManagers in detail.</strong></p>
<p><strong>(3) Run through the implementation of addFunctionAST.</strong></p>
</div>
<div class="section" id="full-code-listing">
<h2><a class="toc-backref" href="#id2"><span class="section-number">4.2. </span>Full Code Listing</a><a class="headerlink" href="#full-code-listing" title="Permalink to this headline">¶</a></h2>
<p>Here is the complete code listing for our running example that JITs lazily from
Kaleidoscope ASTS. To build this example, use:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="c1"># Compile</span>
clang++ -g toy.cpp <span class="sb">`</span>llvm-config --cxxflags --ldflags --system-libs --libs core orcjit native<span class="sb">`</span> -O3 -o toy
<span class="c1"># Run</span>
./toy
</pre></div>
</div>
<p>Here is the code:</p>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="c1">//===- KaleidoscopeJIT.h - A simple JIT for Kaleidoscope --------*- C++ -*-===//</span>
<span class="c1">//</span>
<span class="c1">// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.</span>
<span class="c1">// See https://llvm.org/LICENSE.txt for license information.</span>
<span class="c1">// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception</span>
<span class="c1">//</span>
<span class="c1">//===----------------------------------------------------------------------===//</span>
<span class="c1">//</span>
<span class="c1">// Contains a simple JIT definition for use in the kaleidoscope tutorials.</span>
<span class="c1">//</span>
<span class="c1">//===----------------------------------------------------------------------===//</span>

<span class="cp">#ifndef LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H</span>
<span class="cp">#define LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H</span>

<span class="cp">#include</span> <span class="cpf">&quot;llvm/ADT/STLExtras.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;llvm/ExecutionEngine/ExecutionEngine.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;llvm/ExecutionEngine/JITSymbol.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;llvm/ExecutionEngine/Orc/CompileUtils.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;llvm/ExecutionEngine/Orc/IRCompileLayer.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;llvm/ExecutionEngine/Orc/IRTransformLayer.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;llvm/ExecutionEngine/Orc/IndirectionUtils.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;llvm/ExecutionEngine/Orc/LambdaResolver.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;llvm/ExecutionEngine/RTDyldMemoryManager.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;llvm/ExecutionEngine/SectionMemoryManager.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;llvm/IR/DataLayout.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;llvm/IR/LegacyPassManager.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;llvm/IR/Mangler.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;llvm/Support/DynamicLibrary.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;llvm/Support/Error.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;llvm/Support/raw_ostream.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;llvm/Target/TargetMachine.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;llvm/Transforms/InstCombine/InstCombine.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;llvm/Transforms/Scalar.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&quot;llvm/Transforms/Scalar/GVN.h&quot;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;algorithm&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;cassert&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;cstdlib&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;map&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;memory&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;string&gt;</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf">&lt;vector&gt;</span><span class="cp"></span>

<span class="k">class</span> <span class="nc">PrototypeAST</span><span class="p">;</span>
<span class="k">class</span> <span class="nc">ExprAST</span><span class="p">;</span>

<span class="c1">/// FunctionAST - This class represents a function definition itself.</span>
<span class="k">class</span> <span class="nc">FunctionAST</span> <span class="p">{</span>
  <span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">PrototypeAST</span><span class="o">&gt;</span> <span class="n">Proto</span><span class="p">;</span>
  <span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">ExprAST</span><span class="o">&gt;</span> <span class="n">Body</span><span class="p">;</span>

<span class="k">public</span><span class="o">:</span>
  <span class="n">FunctionAST</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">PrototypeAST</span><span class="o">&gt;</span> <span class="n">Proto</span><span class="p">,</span>
              <span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">ExprAST</span><span class="o">&gt;</span> <span class="n">Body</span><span class="p">)</span>
      <span class="o">:</span> <span class="n">Proto</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">Proto</span><span class="p">)),</span> <span class="n">Body</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">Body</span><span class="p">))</span> <span class="p">{}</span>

  <span class="k">const</span> <span class="n">PrototypeAST</span><span class="o">&amp;</span> <span class="n">getProto</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
  <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">getName</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
  <span class="n">llvm</span><span class="o">::</span><span class="n">Function</span> <span class="o">*</span><span class="n">codegen</span><span class="p">();</span>
<span class="p">};</span>

<span class="c1">/// This will compile FnAST to IR, rename the function to add the given</span>
<span class="c1">/// suffix (needed to prevent a name-clash with the function&#39;s stub),</span>
<span class="c1">/// and then take ownership of the module that the function was compiled</span>
<span class="c1">/// into.</span>
<span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">llvm</span><span class="o">::</span><span class="n">Module</span><span class="o">&gt;</span>
<span class="n">irgenAndTakeOwnership</span><span class="p">(</span><span class="n">FunctionAST</span> <span class="o">&amp;</span><span class="n">FnAST</span><span class="p">,</span> <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="o">&amp;</span><span class="n">Suffix</span><span class="p">);</span>

<span class="k">namespace</span> <span class="n">llvm</span> <span class="p">{</span>
<span class="k">namespace</span> <span class="n">orc</span> <span class="p">{</span>

<span class="k">class</span> <span class="nc">KaleidoscopeJIT</span> <span class="p">{</span>
<span class="k">private</span><span class="o">:</span>
  <span class="n">ExecutionSession</span> <span class="n">ES</span><span class="p">;</span>
  <span class="n">std</span><span class="o">::</span><span class="n">shared_ptr</span><span class="o">&lt;</span><span class="n">SymbolResolver</span><span class="o">&gt;</span> <span class="n">Resolver</span><span class="p">;</span>
  <span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">TargetMachine</span><span class="o">&gt;</span> <span class="n">TM</span><span class="p">;</span>
  <span class="k">const</span> <span class="n">DataLayout</span> <span class="n">DL</span><span class="p">;</span>
  <span class="n">LegacyRTDyldObjectLinkingLayer</span> <span class="n">ObjectLayer</span><span class="p">;</span>
  <span class="n">LegacyIRCompileLayer</span><span class="o">&lt;</span><span class="k">decltype</span><span class="p">(</span><span class="n">ObjectLayer</span><span class="p">),</span> <span class="n">SimpleCompiler</span><span class="o">&gt;</span> <span class="n">CompileLayer</span><span class="p">;</span>

  <span class="k">using</span> <span class="n">OptimizeFunction</span> <span class="o">=</span>
      <span class="n">std</span><span class="o">::</span><span class="n">function</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">Module</span><span class="o">&gt;</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">Module</span><span class="o">&gt;</span><span class="p">)</span><span class="o">&gt;</span><span class="p">;</span>

  <span class="n">LegacyIRTransformLayer</span><span class="o">&lt;</span><span class="k">decltype</span><span class="p">(</span><span class="n">CompileLayer</span><span class="p">),</span> <span class="n">OptimizeFunction</span><span class="o">&gt;</span> <span class="n">OptimizeLayer</span><span class="p">;</span>

  <span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">JITCompileCallbackManager</span><span class="o">&gt;</span> <span class="n">CompileCallbackMgr</span><span class="p">;</span>
  <span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">IndirectStubsManager</span><span class="o">&gt;</span> <span class="n">IndirectStubsMgr</span><span class="p">;</span>

<span class="k">public</span><span class="o">:</span>
  <span class="n">KaleidoscopeJIT</span><span class="p">()</span>
      <span class="o">:</span> <span class="n">Resolver</span><span class="p">(</span><span class="n">createLegacyLookupResolver</span><span class="p">(</span>
            <span class="n">ES</span><span class="p">,</span>
            <span class="p">[</span><span class="k">this</span><span class="p">](</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="o">&amp;</span><span class="n">Name</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">JITSymbol</span> <span class="p">{</span>
              <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">Sym</span> <span class="o">=</span> <span class="n">IndirectStubsMgr</span><span class="o">-&gt;</span><span class="n">findStub</span><span class="p">(</span><span class="n">Name</span><span class="p">,</span> <span class="nb">false</span><span class="p">))</span>
                <span class="k">return</span> <span class="n">Sym</span><span class="p">;</span>
              <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">Sym</span> <span class="o">=</span> <span class="n">OptimizeLayer</span><span class="p">.</span><span class="n">findSymbol</span><span class="p">(</span><span class="n">Name</span><span class="p">,</span> <span class="nb">false</span><span class="p">))</span>
                <span class="k">return</span> <span class="n">Sym</span><span class="p">;</span>
              <span class="k">else</span> <span class="nf">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">Err</span> <span class="o">=</span> <span class="n">Sym</span><span class="p">.</span><span class="n">takeError</span><span class="p">())</span>
                <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">Err</span><span class="p">);</span>
              <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">SymAddr</span> <span class="o">=</span>
                      <span class="n">RTDyldMemoryManager</span><span class="o">::</span><span class="n">getSymbolAddressInProcess</span><span class="p">(</span><span class="n">Name</span><span class="p">))</span>
                <span class="k">return</span> <span class="n">JITSymbol</span><span class="p">(</span><span class="n">SymAddr</span><span class="p">,</span> <span class="n">JITSymbolFlags</span><span class="o">::</span><span class="n">Exported</span><span class="p">);</span>
              <span class="k">return</span> <span class="k">nullptr</span><span class="p">;</span>
            <span class="p">},</span>
            <span class="p">[](</span><span class="n">Error</span> <span class="n">Err</span><span class="p">)</span> <span class="p">{</span> <span class="n">cantFail</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">Err</span><span class="p">),</span> <span class="s">&quot;lookupFlags failed&quot;</span><span class="p">);</span> <span class="p">})),</span>
        <span class="n">TM</span><span class="p">(</span><span class="n">EngineBuilder</span><span class="p">().</span><span class="n">selectTarget</span><span class="p">()),</span> <span class="n">DL</span><span class="p">(</span><span class="n">TM</span><span class="o">-&gt;</span><span class="n">createDataLayout</span><span class="p">()),</span>
        <span class="n">ObjectLayer</span><span class="p">(</span><span class="n">AcknowledgeORCv1Deprecation</span><span class="p">,</span> <span class="n">ES</span><span class="p">,</span>
                    <span class="p">[</span><span class="k">this</span><span class="p">](</span><span class="n">VModuleKey</span> <span class="n">K</span><span class="p">)</span> <span class="p">{</span>
                      <span class="k">return</span> <span class="n">LegacyRTDyldObjectLinkingLayer</span><span class="o">::</span><span class="n">Resources</span><span class="p">{</span>
                          <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">SectionMemoryManager</span><span class="o">&gt;</span><span class="p">(),</span> <span class="n">Resolver</span><span class="p">};</span>
                    <span class="p">}),</span>
        <span class="n">CompileLayer</span><span class="p">(</span><span class="n">AcknowledgeORCv1Deprecation</span><span class="p">,</span> <span class="n">ObjectLayer</span><span class="p">,</span>
                     <span class="n">SimpleCompiler</span><span class="p">(</span><span class="o">*</span><span class="n">TM</span><span class="p">)),</span>
        <span class="n">OptimizeLayer</span><span class="p">(</span><span class="n">AcknowledgeORCv1Deprecation</span><span class="p">,</span> <span class="n">CompileLayer</span><span class="p">,</span>
                      <span class="p">[</span><span class="k">this</span><span class="p">](</span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">Module</span><span class="o">&gt;</span> <span class="n">M</span><span class="p">)</span> <span class="p">{</span>
                        <span class="k">return</span> <span class="nf">optimizeModule</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">M</span><span class="p">));</span>
                      <span class="p">}),</span>
        <span class="n">CompileCallbackMgr</span><span class="p">(</span><span class="n">cantFail</span><span class="p">(</span><span class="n">orc</span><span class="o">::</span><span class="n">createLocalCompileCallbackManager</span><span class="p">(</span>
            <span class="n">TM</span><span class="o">-&gt;</span><span class="n">getTargetTriple</span><span class="p">(),</span> <span class="n">ES</span><span class="p">,</span> <span class="mi">0</span><span class="p">)))</span> <span class="p">{</span>
    <span class="k">auto</span> <span class="n">IndirectStubsMgrBuilder</span> <span class="o">=</span>
      <span class="n">orc</span><span class="o">::</span><span class="n">createLocalIndirectStubsManagerBuilder</span><span class="p">(</span><span class="n">TM</span><span class="o">-&gt;</span><span class="n">getTargetTriple</span><span class="p">());</span>
    <span class="n">IndirectStubsMgr</span> <span class="o">=</span> <span class="n">IndirectStubsMgrBuilder</span><span class="p">();</span>
    <span class="n">llvm</span><span class="o">::</span><span class="n">sys</span><span class="o">::</span><span class="n">DynamicLibrary</span><span class="o">::</span><span class="n">LoadLibraryPermanently</span><span class="p">(</span><span class="k">nullptr</span><span class="p">);</span>
  <span class="p">}</span>

  <span class="n">TargetMachine</span> <span class="o">&amp;</span><span class="n">getTargetMachine</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="o">*</span><span class="n">TM</span><span class="p">;</span> <span class="p">}</span>

  <span class="n">VModuleKey</span> <span class="n">addModule</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">Module</span><span class="o">&gt;</span> <span class="n">M</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// Add the module to the JIT with a new VModuleKey.</span>
    <span class="k">auto</span> <span class="n">K</span> <span class="o">=</span> <span class="n">ES</span><span class="p">.</span><span class="n">allocateVModule</span><span class="p">();</span>
    <span class="n">cantFail</span><span class="p">(</span><span class="n">OptimizeLayer</span><span class="p">.</span><span class="n">addModule</span><span class="p">(</span><span class="n">K</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">M</span><span class="p">)));</span>
    <span class="k">return</span> <span class="n">K</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="n">Error</span> <span class="n">addFunctionAST</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">FunctionAST</span><span class="o">&gt;</span> <span class="n">FnAST</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// Move ownership of FnAST to a shared pointer - C++11 lambdas don&#39;t support</span>
    <span class="c1">// capture-by-move, which is be required for unique_ptr.</span>
    <span class="k">auto</span> <span class="n">SharedFnAST</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">shared_ptr</span><span class="o">&lt;</span><span class="n">FunctionAST</span><span class="o">&gt;</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">FnAST</span><span class="p">));</span>

    <span class="c1">// Set the action to compile our AST. This lambda will be run if/when</span>
    <span class="c1">// execution hits the compile callback (via the stub).</span>
    <span class="c1">//</span>
    <span class="c1">// The steps to compile are:</span>
    <span class="c1">// (1) IRGen the function.</span>
    <span class="c1">// (2) Add the IR module to the JIT to make it executable like any other</span>
    <span class="c1">//     module.</span>
    <span class="c1">// (3) Use findSymbol to get the address of the compiled function.</span>
    <span class="c1">// (4) Update the stub pointer to point at the implementation so that</span>
    <span class="c1">///    subsequent calls go directly to it and bypass the compiler.</span>
    <span class="c1">// (5) Return the address of the implementation: this lambda will actually</span>
    <span class="c1">//     be run inside an attempted call to the function, and we need to</span>
    <span class="c1">//     continue on to the implementation to complete the attempted call.</span>
    <span class="c1">//     The JIT runtime (the resolver block) will use the return address of</span>
    <span class="c1">//     this function as the address to continue at once it has reset the</span>
    <span class="c1">//     CPU state to what it was immediately before the call.</span>
    <span class="k">auto</span> <span class="n">CompileAction</span> <span class="o">=</span> <span class="p">[</span><span class="k">this</span><span class="p">,</span> <span class="n">SharedFnAST</span><span class="p">]()</span> <span class="p">{</span>
      <span class="k">auto</span> <span class="n">M</span> <span class="o">=</span> <span class="n">irgenAndTakeOwnership</span><span class="p">(</span><span class="o">*</span><span class="n">SharedFnAST</span><span class="p">,</span> <span class="s">&quot;$impl&quot;</span><span class="p">);</span>
      <span class="n">addModule</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">M</span><span class="p">));</span>
      <span class="k">auto</span> <span class="n">Sym</span> <span class="o">=</span> <span class="n">findSymbol</span><span class="p">(</span><span class="n">SharedFnAST</span><span class="o">-&gt;</span><span class="n">getName</span><span class="p">()</span> <span class="o">+</span> <span class="s">&quot;$impl&quot;</span><span class="p">);</span>
      <span class="n">assert</span><span class="p">(</span><span class="n">Sym</span> <span class="o">&amp;&amp;</span> <span class="s">&quot;Couldn&#39;t find compiled function?&quot;</span><span class="p">);</span>
      <span class="n">JITTargetAddress</span> <span class="n">SymAddr</span> <span class="o">=</span> <span class="n">cantFail</span><span class="p">(</span><span class="n">Sym</span><span class="p">.</span><span class="n">getAddress</span><span class="p">());</span>
      <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">Err</span> <span class="o">=</span> <span class="n">IndirectStubsMgr</span><span class="o">-&gt;</span><span class="n">updatePointer</span><span class="p">(</span>
              <span class="n">mangle</span><span class="p">(</span><span class="n">SharedFnAST</span><span class="o">-&gt;</span><span class="n">getName</span><span class="p">()),</span> <span class="n">SymAddr</span><span class="p">))</span> <span class="p">{</span>
        <span class="n">logAllUnhandledErrors</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">Err</span><span class="p">),</span> <span class="n">errs</span><span class="p">(),</span>
                              <span class="s">&quot;Error updating function pointer: &quot;</span><span class="p">);</span>
        <span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
      <span class="p">}</span>

      <span class="k">return</span> <span class="n">SymAddr</span><span class="p">;</span>
    <span class="p">};</span>

    <span class="c1">// Create a CompileCallback using the CompileAction - this is the re-entry</span>
    <span class="c1">// point into the compiler for functions that haven&#39;t been compiled yet.</span>
    <span class="k">auto</span> <span class="n">CCAddr</span> <span class="o">=</span> <span class="n">cantFail</span><span class="p">(</span>
        <span class="n">CompileCallbackMgr</span><span class="o">-&gt;</span><span class="n">getCompileCallback</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">CompileAction</span><span class="p">)));</span>

    <span class="c1">// Create an indirect stub. This serves as the functions &quot;canonical</span>
    <span class="c1">// definition&quot; - an unchanging (constant address) entry point to the</span>
    <span class="c1">// function implementation.</span>
    <span class="c1">// Initially we point the stub&#39;s function-pointer at the compile callback</span>
    <span class="c1">// that we just created. When the compile action for the callback is run we</span>
    <span class="c1">// will update the stub&#39;s function pointer to point at the function</span>
    <span class="c1">// implementation that we just implemented.</span>
    <span class="k">if</span> <span class="p">(</span><span class="k">auto</span> <span class="n">Err</span> <span class="o">=</span> <span class="n">IndirectStubsMgr</span><span class="o">-&gt;</span><span class="n">createStub</span><span class="p">(</span>
            <span class="n">mangle</span><span class="p">(</span><span class="n">SharedFnAST</span><span class="o">-&gt;</span><span class="n">getName</span><span class="p">()),</span> <span class="n">CCAddr</span><span class="p">,</span> <span class="n">JITSymbolFlags</span><span class="o">::</span><span class="n">Exported</span><span class="p">))</span>
      <span class="k">return</span> <span class="n">Err</span><span class="p">;</span>

    <span class="k">return</span> <span class="n">Error</span><span class="o">::</span><span class="n">success</span><span class="p">();</span>
  <span class="p">}</span>

  <span class="n">JITSymbol</span> <span class="n">findSymbol</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">Name</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="n">OptimizeLayer</span><span class="p">.</span><span class="n">findSymbol</span><span class="p">(</span><span class="n">mangle</span><span class="p">(</span><span class="n">Name</span><span class="p">),</span> <span class="nb">true</span><span class="p">);</span>
  <span class="p">}</span>

  <span class="kt">void</span> <span class="n">removeModule</span><span class="p">(</span><span class="n">VModuleKey</span> <span class="n">K</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">cantFail</span><span class="p">(</span><span class="n">OptimizeLayer</span><span class="p">.</span><span class="n">removeModule</span><span class="p">(</span><span class="n">K</span><span class="p">));</span>
  <span class="p">}</span>

<span class="k">private</span><span class="o">:</span>
  <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">mangle</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="o">&amp;</span><span class="n">Name</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">MangledName</span><span class="p">;</span>
    <span class="n">raw_string_ostream</span> <span class="nf">MangledNameStream</span><span class="p">(</span><span class="n">MangledName</span><span class="p">);</span>
    <span class="n">Mangler</span><span class="o">::</span><span class="n">getNameWithPrefix</span><span class="p">(</span><span class="n">MangledNameStream</span><span class="p">,</span> <span class="n">Name</span><span class="p">,</span> <span class="n">DL</span><span class="p">);</span>
    <span class="k">return</span> <span class="n">MangledNameStream</span><span class="p">.</span><span class="n">str</span><span class="p">();</span>
  <span class="p">}</span>

  <span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">Module</span><span class="o">&gt;</span> <span class="n">optimizeModule</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">Module</span><span class="o">&gt;</span> <span class="n">M</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// Create a function pass manager.</span>
    <span class="k">auto</span> <span class="n">FPM</span> <span class="o">=</span> <span class="n">llvm</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">legacy</span><span class="o">::</span><span class="n">FunctionPassManager</span><span class="o">&gt;</span><span class="p">(</span><span class="n">M</span><span class="p">.</span><span class="n">get</span><span class="p">());</span>

    <span class="c1">// Add some optimizations.</span>
    <span class="n">FPM</span><span class="o">-&gt;</span><span class="n">add</span><span class="p">(</span><span class="n">createInstructionCombiningPass</span><span class="p">());</span>
    <span class="n">FPM</span><span class="o">-&gt;</span><span class="n">add</span><span class="p">(</span><span class="n">createReassociatePass</span><span class="p">());</span>
    <span class="n">FPM</span><span class="o">-&gt;</span><span class="n">add</span><span class="p">(</span><span class="n">createGVNPass</span><span class="p">());</span>
    <span class="n">FPM</span><span class="o">-&gt;</span><span class="n">add</span><span class="p">(</span><span class="n">createCFGSimplificationPass</span><span class="p">());</span>
    <span class="n">FPM</span><span class="o">-&gt;</span><span class="n">doInitialization</span><span class="p">();</span>

    <span class="c1">// Run the optimizations over all functions in the module being added to</span>
    <span class="c1">// the JIT.</span>
    <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="o">&amp;</span><span class="nl">F</span> <span class="p">:</span> <span class="o">*</span><span class="n">M</span><span class="p">)</span>
      <span class="n">FPM</span><span class="o">-&gt;</span><span class="n">run</span><span class="p">(</span><span class="n">F</span><span class="p">);</span>

    <span class="k">return</span> <span class="n">M</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">};</span>

<span class="p">}</span> <span class="c1">// end namespace orc</span>
<span class="p">}</span> <span class="c1">// end namespace llvm</span>

<span class="cp">#endif </span><span class="c1">// LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H</span>
</pre></div>
</div>
<p><a class="reference external" href="BuildingAJIT5.html">Next: Remote-JITing – Process-isolation and laziness-at-a-distance</a></p>
</div>
</div>


            <div class="clearer"></div>
          </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="General Index"
             >index</a></li>
        <li class="right" >
          <a href="BuildingAJIT5.html" title="5. Building a JIT: Remote-JITing – Process Isolation and Laziness at a Distance"
             >next</a> |</li>
        <li class="right" >
          <a href="BuildingAJIT3.html" title="3. Building a JIT: Per-function Lazy Compilation"
             >previous</a> |</li>
  <li><a href="http://llvm.org/">LLVM Home</a>&nbsp;|&nbsp;</li>
  <li><a href="../index.html">Documentation</a>&raquo;</li>

          <li class="nav-item nav-item-1"><a href="index.html" >LLVM Tutorial: Table of Contents</a> &#187;</li>
        <li class="nav-item nav-item-this"><a href=""><span class="section-number">4. </span>Building a JIT: Extreme Laziness - Using Compile Callbacks to JIT from ASTs</a></li> 
      </ul>
    </div>
    <div class="footer" role="contentinfo">
        &#169; Copyright 2003-2020, LLVM Project.
      Last updated on 2020-09-20.
      Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
    </div>
  </body>
</html>